import re,struct,random,os,sys

datPath= r"D:\JX3facedataset"#捏脸数据保存路径
bone_cnt=49#骨骼参数数量
all_max=[128]*bone_cnt
all_min=[-128]*bone_cnt

def gernateface(num):
    #捏脸文件头
    facestringtemplate=b"\x43\x4E\x44\x4B\xDB\x63\xFA\x22\x23\x09\x00\x00\x23\x09\x00\x00\x72\x65\x74\x75\x72\x6E\x20"#dat文件头
    #捏脸骨骼数据
    bonedata=b"{tBone={NOSE_SIZE=%d,UP_LIP_OUT=%d,NOSEBOW_WIDTH=%d,MOUTH_OPEN=%d,CHEEK_Y=%d,EYE_OPEN=%d,FACE_Y=%d,MOUTH_END_L=%d,JAW_LENGTH=%d,UP_LIP=%d,EYE_DIST=%d,NOSETOP_POS_Y=%d,EYE_DIRC=%d,EYEBOW_OUT=%d,MOUTH_OUT=%d,RIDGE_Y=%d,MOUTH_END=%d,NOSEBOW_BEND=%d,JAW_WIDTH=%d,LOW_LIP_POS=%d,PUPIL_DIRC=%d,NOSETOP_POS_Z=%d,MOUTH_POS=%d,FACE_SCALE=%d,UP_LID_POS=%d,FACE_Z=%d,NOSETOP_WIDTH=%d,PUPIL_SIZE=%d,UP_FACE=%d,EYEBOW_POS=%d,EYEBOW_DIRC=%d,UP_LIP_POS=%d,EYE_SIZE=%d,MOUTH_ROT=%d,OUT=%d,EYE_POS=%d,MOUTH_END_R=%d,NOSETOP_UP=%d,EYECROW_Y=%d,JAW_END=%d,JAW_ROT=%d,LOW_LIP_OUT=%d,JAW_POS=%d,LOW_FACE=%d,CHEEK_Z=%d,LOW_LIP=%d,MOUTH_SIZE=%d,NOSE_HEIGHT=%d,LOW_LID_POS=%d}"
    facestringtemplate+=bonedata
    facestringtemplate+=b",nDecorationID=0,tDecal={EYE_SHADOW_FLASH2={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},EYE_SHADOW1={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},LIP_LIGHT={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},BLUSHER_MOUSTACHE={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},EYE_LINE={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=1,fValue2=1},EYE_SHADOW_FLASH1={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},DECAL={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},BROW={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=1,fValue2=1},EYE_LIGHT={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=1,fValue2=1},LIP_FLASH={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},EYE_SHADOW4={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},IRIS_RIGHT={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=1,fValue2=1},EYE_SHADOW={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},IRIS_LEFT={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=1,fValue2=1},EYE_SHADOW2={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},BASE={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=1,fValue2=1},EYE_SHADOW_FLASH3={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},LIP_GLOSS={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=1,fValue2=1},EYE_SHADOW_FLASH4={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},EYE_SHADOW3={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},LIP_OVERLAP={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1}},nMajorVersion=1,nRoleType=1,nVersion=5}"
    for n in range(num):
        filename="d:/JX3facedataset/%d.dat" % n
        randomdata = []
        for i in range(bone_cnt):
            randomdata.append(random.randint(all_min[i],all_max[i]))
        with open(filename,'wb') as fp:
            bytestream=facestringtemplate % tuple(randomdata)
            fp.write(bytestream)

def writeface(array):
    intarray=[]
    for i in range(bone_cnt):
        intarray.append(int(array[i]))
    #捏脸文件头
    facestringtemplate=b"\x43\x4E\x44\x4B\xDB\x63\xFA\x22\x23\x09\x00\x00\x23\x09\x00\x00\x72\x65\x74\x75\x72\x6E\x20"#dat文件头
    #捏脸骨骼数据
    bonedata=b"{tBone={NOSE_SIZE=%d,UP_LIP_OUT=%d,NOSEBOW_WIDTH=%d,MOUTH_OPEN=%d,CHEEK_Y=%d,EYE_OPEN=%d,FACE_Y=%d,MOUTH_END_L=%d,JAW_LENGTH=%d,UP_LIP=%d,EYE_DIST=%d,NOSETOP_POS_Y=%d,EYE_DIRC=%d,EYEBOW_OUT=%d,MOUTH_OUT=%d,RIDGE_Y=%d,MOUTH_END=%d,NOSEBOW_BEND=%d,JAW_WIDTH=%d,LOW_LIP_POS=%d,PUPIL_DIRC=%d,NOSETOP_POS_Z=%d,MOUTH_POS=%d,FACE_SCALE=%d,UP_LID_POS=%d,FACE_Z=%d,NOSETOP_WIDTH=%d,PUPIL_SIZE=%d,UP_FACE=%d,EYEBOW_POS=%d,EYEBOW_DIRC=%d,UP_LIP_POS=%d,EYE_SIZE=%d,MOUTH_ROT=%d,OUT=%d,EYE_POS=%d,MOUTH_END_R=%d,NOSETOP_UP=%d,EYECROW_Y=%d,JAW_END=%d,JAW_ROT=%d,LOW_LIP_OUT=%d,JAW_POS=%d,LOW_FACE=%d,CHEEK_Z=%d,LOW_LIP=%d,MOUTH_SIZE=%d,NOSE_HEIGHT=%d,LOW_LID_POS=%d}"
    facestringtemplate+=bonedata
    facestringtemplate+=b",nDecorationID=0,tDecal={EYE_SHADOW_FLASH2={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},EYE_SHADOW1={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},LIP_LIGHT={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},BLUSHER_MOUSTACHE={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},EYE_LINE={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=1,fValue2=1},EYE_SHADOW_FLASH1={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},DECAL={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},BROW={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=1,fValue2=1},EYE_LIGHT={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=1,fValue2=1},LIP_FLASH={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},EYE_SHADOW4={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},IRIS_RIGHT={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=1,fValue2=1},EYE_SHADOW={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},IRIS_LEFT={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=1,fValue2=1},EYE_SHADOW2={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},BASE={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=1,fValue2=1},EYE_SHADOW_FLASH3={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},LIP_GLOSS={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=1,fValue2=1},EYE_SHADOW_FLASH4={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},EYE_SHADOW3={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1},LIP_OVERLAP={fValue1=0,nColorID=0,bUse=false,fValue3=1,nShowID=0,fValue2=1}},nMajorVersion=1,nRoleType=1,nVersion=5}"
    filename="output.dat"
    with open(filename,'wb') as fp:
        bytestream=facestringtemplate % tuple(intarray)
        fp.write(bytestream)

def faceparsedata(facestring):
    result=[]
    value = re.compile(r"=([0-9\-]{1,})")
    values = re.findall(value, facestring)
    for i in values:
        result.append(int(i)*1.0)

    return result[0:bone_cnt]

if __name__ == '__main__':
    #收敛脸型参数最大最小值
    
    all_max=faceparsedata("{tBone={NOSE_SIZE=105,UP_LIP_OUT=21,NOSEBOW_WIDTH=126,MOUTH_OPEN=20,CHEEK_Y=116,EYE_OPEN=32,FACE_Y=126,MOUTH_END_L=22,JAW_LENGTH=21,UP_LIP=10,EYE_DIST=40,NOSETOP_POS_Y=33,EYE_DIRC=32,EYEBOW_OUT=126,MOUTH_OUT=10,RIDGE_Y=49,MOUTH_END=56,NOSEBOW_BEND=55,JAW_WIDTH=126,LOW_LIP_POS=89,PUPIL_DIRC=15,NOSETOP_POS_Z=20,MOUTH_POS=13,FACE_SCALE=57,UP_LID_POS=95,FACE_Z=67,NOSETOP_WIDTH=126,PUPIL_SIZE=18,UP_FACE=126,EYEBOW_POS=41,EYEBOW_DIRC=90,UP_LIP_POS=25,EYE_SIZE=18,MOUTH_ROT=10,OUT=10,EYE_POS=15,MOUTH_END_R=22,NOSETOP_UP=127,EYECROW_Y=65,JAW_END=38,JAW_ROT=126,LOW_LIP_OUT=25,JAW_POS=126,LOW_FACE=126,CHEEK_Z=33,LOW_LIP=97,MOUTH_SIZE=55,NOSE_HEIGHT=20,LOW_LID_POS=87}")
    all_min=faceparsedata("{tBone={NOSE_SIZE=-92,UP_LIP_OUT=-36,NOSEBOW_WIDTH=-128,MOUTH_OPEN=-20,CHEEK_Y=-128,EYE_OPEN=-28,FACE_Y=-128,MOUTH_END_L=-22,JAW_LENGTH=-39,UP_LIP=-69,EYE_DIST=-5,NOSETOP_POS_Y=-66,EYE_DIRC=-42,EYEBOW_OUT=-85,MOUTH_OUT=-78,RIDGE_Y=49,MOUTH_END=-32,NOSEBOW_BEND=-76,JAW_WIDTH=-36,LOW_LIP_POS=-29,PUPIL_DIRC=-53,NOSETOP_POS_Z=-128,MOUTH_POS=-23,FACE_SCALE=-119,UP_LID_POS=-10,FACE_Z=-112,NOSETOP_WIDTH=-67,PUPIL_SIZE=-96,UP_FACE=-107,EYEBOW_POS=-78,EYEBOW_DIRC=-61,UP_LIP_POS=-32,EYE_SIZE=-25,MOUTH_ROT=-10,OUT=10,EYE_POS=-46,MOUTH_END_R=-22,NOSETOP_UP=-128,EYECROW_Y=-128,JAW_END=-105,JAW_ROT=-69,LOW_LIP_OUT=-6,JAW_POS=-128,LOW_FACE=-128,CHEEK_Z=-15,LOW_LIP=-39,MOUTH_SIZE=-27,NOSE_HEIGHT=-128,LOW_LID_POS=-28}")
    #usage:python J3FaceParser.py --gen
    if (len(sys.argv)==2 and sys.argv[1]=="--gen"):
        gernateface(10000)
    
    if (len(sys.argv)==2 and sys.argv[1]=="--restore"):
        writeface([45.0, 8.0, -71.0, -6.0, 71.0, -22.0, -77.0, -22.0, -28.0, -39.0, 37.0, -40.0, 7.0, -81.0, -30.0, 49.0, -20.0, 30.0, 6.0, 44.0, -27.0, -17.0, 13.0, 26.0, 3.0, -99.0, 68.0, 10.0, -18.0, -76.0, 29.0, 14.0, 10.0, 3.0, 10.0, 8.0, -20.0, 82.0, -59.0, -56.0, 89.0, 2.0, -17.0, -44.0, 19.0, -12.0, 32.0, -99.0, 36.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
    if (len(sys.argv)==1):
        for root,dir,filenames in os.walk(datPath):
            for name in filenames:
                with open(root+'/'+name,'rb') as fp:
                    datastr=fp.read().decode('ascii','ignore')
                with open("D:/db_description",'ab+') as f:
                    f.write(struct.pack("i",int(name.split('.')[0])))#第一个字节是文件名
                    face=faceparsedata(datastr)
                    print(name.split('.')[0],face)
                    for i in face:
                        f.write(struct.pack("f",i))#后续字节是脸型骨骼数据
